use std::time::Duration;

use base_data::channel::{event::ChannelEvent, ChannelState, CommandMsg, EndReason};
use tools::{error::Error, utils::gen_id::get_now_duration, ResultEx, ResultNull};
use tracing::{debug, error, trace};

use crate::sip2::{
	dialog::{
		dialog::{Dialog, DialogState},
		sipdata::SipData,
		INV_OVER, WAIT_REPEAT_TIME,
	},
	SipDirection, SipMethod,
};

use super::{send_wait_resp, SipTimeOver, SipTransaction, SipTransactionState, WaitSipMessage};

#[inline]
pub fn start_tran(dialog: &mut Dialog) {
	trace!("开始INVITE_SERVER事务");
	dialog.set_tran_state(SipTransactionState::Proceeding);
	dialog.start_time = get_now_duration();
	if dialog.over_time == SipTimeOver::Zero {
		dialog.over_time = SipTimeOver::TranOvertime(INV_OVER);
	}
	dialog.retry_time = Duration::ZERO;
	dialog.last_send_bytes = None;
	dialog.wait_resp_method = WaitSipMessage::None;

	let buf = dialog.generate_invite_try();

	dialog.send_to_remote(buf);
}

///处理事务收到的sip协议的消息
#[inline]
pub fn handle_tran_msg(dialog: &mut Dialog, sip_data: SipData) -> ResultNull {
	match sip_data.direction {
		SipDirection::Request(ref m) => match (m, dialog.tran_state()) {
			//complete收到的ack是正常确认.根据sip协议,一般这里是收到300-699之间的响应.
			//但这里修改成收到200也进complete.
			(SipMethod::Ack, SipTransactionState::Completed) => match dialog.wait_resp_method {
				WaitSipMessage::DilaogVerify => {
					dialog.start_time = get_now_duration();
					dialog.retry_time = Duration::ZERO;
					dialog.state = DialogState::Answered;
					dialog.over_time = SipTimeOver::Finish(WAIT_REPEAT_TIME);
					dialog.set_tran_state(SipTransactionState::Confirmed);
					dialog.wait_resp_method = WaitSipMessage::None;

					dialog.set_sdp(&sip_data.body)?;
					dialog.send_to_business(ChannelEvent::ChannelAnswer(dialog.id));
				}
				WaitSipMessage::AckOther => {
					dialog.start_time = get_now_duration();
					dialog.retry_time = Duration::ZERO;
					//接收到的是挂断回复的ack..
					dialog.state = DialogState::Hangup;
					dialog.over_time = SipTimeOver::Finish(WAIT_REPEAT_TIME);
					dialog.set_tran_state(SipTransactionState::Confirmed);
					dialog.wait_resp_method = WaitSipMessage::None;
					//这里是收到挂断的回复,正常这里不应该再向业务发消息
				}
				_ => debug!("收到无效的消息."),
			},

			//取消的操作.等待结束
			(SipMethod::Cancel, _) | (SipMethod::Bye, _) => {
				//只有不在确认状态的时候,才设置状态,并发回应,其他时候仅回应.
				if dialog.tran_state() < SipTransactionState::Confirmed {
					//回复一个200收到.
					let buf = dialog.generate_receive(&sip_data);
					dialog.send_to_remote(buf);

					dialog.start_time = get_now_duration();
					dialog.set_tran_state(SipTransactionState::Completed);
					dialog.over_time = SipTimeOver::TranOvertime(32 * crate::sip2::dialog::T1);
					let buf = dialog.generate_hungup_with_reason(EndReason::CallerPending);
					send_wait_resp(dialog, WaitSipMessage::AckOther, buf);

					dialog.send_to_business(ChannelEvent::ChannelHangup(
						dialog.id,
						sip_data.to_hangup_reason(),
					));
					dialog.send_to_business(ChannelEvent::ChannelCallState(
						dialog.id,
						ChannelState::Hangup,
					));
				}
			}

			//这个Invite算是收到重复的..在一个事务当中不应该收到这个消息的
			(SipMethod::Invite, SipTransactionState::Proceeding) => {
				// let buf = dialog.generate_invite_try();
				// dialog.send_to_remote( buf);
			}

			//收到一个重复的消息,什么都不做好了.
			(SipMethod::Ack, SipTransactionState::Confirmed) => trace!("收到重复的消息."),

			_ => debug!(
				"收到一个不对应的消息.跳过.当前状态:{:?},消息:{:?}",
				dialog.tran_state(),
				sip_data
			),
		},
		_ => {}
	}

	Ok(())
}
///处理事务收到的命令消息
/// 当接收到事件时,根据情况上传状态修改.
#[inline]
pub fn handle_command_msg(dialog: &mut Dialog, cmd_msg: CommandMsg) -> ResultNull {
	match cmd_msg {
		CommandMsg::Ringing => {
			if dialog.tran_state() != SipTransactionState::Proceeding {
				return Err(Error::LogicalError(
					"只有在Proceeding状态下,才能发送180消息.",
				));
			}

			let buf = dialog.generate_ringing();

			//目前180消息不进行等待
			dialog.send_to_remote(buf);
			dialog.send_to_business(ChannelEvent::ChannelCallState(
				dialog.id,
				ChannelState::Ringing,
			));
		}
		//发送成功创建消息.需要处理sdp
		CommandMsg::AnswerCall(_) => {
			trace!("收到接通消息,准备发送200OK");
			if dialog.tran_state() != SipTransactionState::Proceeding {
				dialog.create_to_tag();
				return Err(Error::LogicalError(
					"只有在Proceeding状态下,才能发送成功创建消息.",
				));
			}

			let buf = dialog.generate_answer();
			dialog.set_tran_state(SipTransactionState::Completed);
			send_wait_resp(dialog, WaitSipMessage::DilaogVerify, buf);
			dialog.send_to_business(ChannelEvent::ChannelCallState(
				dialog.id,
				ChannelState::Answered,
			));
			dialog.state = DialogState::Answered;
		}
		//生成500错误,当成直接挂断消息的操作.在收到此消息时,认为是出现了异常情况
		CommandMsg::KillChannel(_) => {
			if dialog.tran_state() == SipTransactionState::Proceeding {
				dialog.create_to_tag();
				let buf = dialog.generate_internal_error();
				dialog.set_tran_state(SipTransactionState::Completed);
				send_wait_resp(dialog, WaitSipMessage::AckOther, buf);
			} else {
				dialog.state = DialogState::NeedKill;
			}

			dialog.send_to_business(ChannelEvent::ChannelCallState(
				dialog.id,
				ChannelState::Hangup,
			));
		}
		CommandMsg::HangupChannel(_, reason) => {
			dialog.create_to_tag();
			if dialog.tran_state() == SipTransactionState::Proceeding {
				let buf = dialog.generate_hungup_with_reason(reason);
				dialog.set_tran_state(SipTransactionState::Completed);
				send_wait_resp(dialog, WaitSipMessage::AckOther, buf);
				dialog.send_to_business(ChannelEvent::ChannelHangup(
					dialog.id,
					EndReason::InitiativeHangup,
				));
			} else {
				dialog.state = DialogState::NeedKill;
			}

			dialog.send_to_business(ChannelEvent::ChannelCallState(
				dialog.id,
				ChannelState::Hangup,
			));
		}

		//以下操作应该在上层进行处理
		CommandMsg::Originate { .. } | CommandMsg::BridgeChannel(..) => {
			error!("事务处理不应该收到当前事务.应在上层处理")
		}
		//未列出的代表直接忽略
		CommandMsg::SetVar | _ => debug!("收到一个无效的命令消息."),
	}

	Ok(())
}

///处理事务结束的操作..
/// 返回true表示事务结束时dialog同时结束.
#[inline]
pub fn end_tran(dialog: &mut Dialog) -> ResultEx<bool> {
	//当事务已经进入到接收确认阶段,但又收到挂断...则再启动一个事务进行处理.
	//未成功对话本身就要挂断,所以不需要再进行后续事务
	if dialog.state == DialogState::NeedKill {
		Ok(true)
	} else {
		dialog.last_send_bytes = None;
		dialog.tran_handler = SipTransaction::NoN;

		Ok(dialog.state != DialogState::Answered)
	}
}

#[inline]
pub fn handle_time_over(dialog: &mut Dialog, to: SipTimeOver) -> ResultNull {
	match to {
		//只要是超时,则不算成功创建dialog
		SipTimeOver::TranOvertime(_) | SipTimeOver::CallOvertime(_) => {
			dialog.set_tran_state(SipTransactionState::Terminated);
			dialog.state = DialogState::Hangup;
			dialog.send_to_business(ChannelEvent::ChannelHangup(dialog.id, EndReason::Overtime));
		}
		SipTimeOver::Retry(_) => {
			dialog.retry_send()?;
		}
		_ => {}
	}

	if dialog.tran_state() == SipTransactionState::Confirmed {
		dialog.set_tran_state(SipTransactionState::Terminated);
	}

	Ok(())
}
